import cv, cv2
import string
from gui import Frame_Principal as miFP
import gui
import wx
import numpy as np
import matplotlib.pyplot as plt


def best_match(template_img, scene_img, minsize, maxsize):
    """ Get the best match for a template image within a scene image,
        rescaling the template width between minsize and maxsize
        while maintaining the aspect ratio.
        Returns two 2-tuples of ints:
            corner is the (x,y) position of the upper-left corner of the template in the scene
            wh is (width, height)
    """
    # widths is all the widths to try
    widths = np.arange(minsize, maxsize, dtype=int)
    # aspect_ratio is height/width of the template image
    aspect_ratio = template_img.shape[0] / float(template_img.shape[1])
    # heights is all the heights to try
    heights = np.asarray(aspect_ratio*widths, dtype=int)
    
    # best_scores will store the best score for each width
    best_scores = np.zeros(len(widths))
    # best_positions will store the best (x,y) positions of the template for each width
    best_positions = np.zeros([len(widths), 2], dtype=int)
    
    # scan widths
    for isize in range(widths.size):
        # log
        print "resizing to width = %d" % widths[isize]
        
        # resize
        resized_template_img = cv2.resize(template_img, (widths[isize], heights[isize]))
        
        # match
        scores = cv2.matchTemplate(scene_img, resized_template_img, method=cv2.TM_CCORR_NORMED)

        # get best score and position
        min_score, max_score, (min_x, min_y), (max_x, max_y) = cv2.minMaxLoc(scores)
        
        # store best score and position
        best_scores[isize] = max_score
        best_positions[isize] = [max_x, max_y]
        
    # choose best overall match
    best_isize = np.argmax(best_scores)
    best_width = widths[best_isize]
    best_position = best_positions[best_isize]
    
    # plot scores
    plt.plot(widths, best_scores)
    plt.arrow(widths[best_isize], 0, 0, 1, color='r')
    plt.xlabel('template width')
    plt.ylabel('score')
    
    # return
    return tuple(best_positions[best_isize]), (widths[best_isize], heights[best_isize])

def imshow_highlighted(img, corner, wh, rgb=(0,255,0), stroke=5):
    """ Show an image with a highlighted rectangle.
        corner is a (x_upperleft, y_upperleft) tuple of ints,
        wh is a (width, height) tuple of ints,
        rgb is an optional (r,g,b) tuple (default green),
        stroke is an optional number of pixels for rectangle stroke (default 5).
    """
    # copy the image so we don't modify the original
    img_highlighted = img[:,:,[2,1,0]].copy()
    
    # add a rectangle
    cv2.rectangle(img_highlighted, corner, (corner[0]+wh[0], corner[1]+wh[1]), rgb, stroke)
    
    # show
    plt.imshow(img_highlighted)


class MiFrame (miFP):
    def __init__(self,fps = 15):
        miFP.__init__(self, None )
        self.WinFrame = miFP
        self.capture = cv2.VideoCapture(0)
        self.capture.set(cv.CV_CAP_PROP_FRAME_WIDTH, 1280)
        self.capture.set(cv.CV_CAP_PROP_FRAME_HEIGHT, 1024)
        ret, frame = self.capture.read()
        
        height, width = frame.shape[:2]
        #self.panelDerecho.SetSize((width, height))
        #self.panelIzquierdo.SetSize((width, height))
        
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

        self.bmp    = wx.BitmapFromBuffer(width, height, frame)
        self.bmpraw = wx.BitmapFromBuffer(width, height, frame)
        
        self.size_PD = self.panelIzquierdo.GetSize()
        self.size_PI  = self.panelDerecho.GetSize()

        self.timer = wx.Timer(self)
        self.timer.Start(1000./15)

        self.panelIzquierdo.Bind(wx.EVT_PAINT,self.OnPaintIz)
        self.panelDerecho.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_TIMER, self.NextFrame)
        
    def OnPaintIz(self, evt):
        dc = wx.BufferedPaintDC(self.panelIzquierdo)
        dc.DrawBitmap(self.bmpraw, 0, 0)
    
    def OnPaint(self, evt):
        dc = wx.BufferedPaintDC(self.panelDerecho)
        dc.DrawBitmap(self.bmp, 0, 0)

    def Frame_PrincipalOnChar( self, evt ):
        key = chr(evt.GetKeyCode())
        if ord(key) == 27:
            self.capture.release()
            self.timer.Stop()
            self.Destroy()
        elif ord(key) == 65:
            print "convirtiendo\n"
            self.extracto = self.imagen[100:140,100:140]
            print best_match(self.imagen, self.extracto, 10, 30)
        evt.Skip()
        
    def NextFrame(self, event):
        ret, img2 = self.capture.read()
        img3 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
        frame = cv2.Canny(img3,self.m_slider_min.GetValue(),self.m_slider_max.GetValue())
        if ret:
            frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2RGB)
            self.bmpraw.CopyFromBuffer(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB))
            self.bmp.CopyFromBuffer(frame)
            self.panelDerecho.Refresh()
            self.panelIzquierdo.Refresh()
            self.imagen = img2
               
        event.Skip()

        

aplicacion = wx.PySimpleApp()
frame_usuario = MiFrame()
frame_usuario.Show()
aplicacion.MainLoop()

